bitkeeper revision 1.184.5.1 (3ead2bacOfPX2Bo4kzErV1yUs0q1qA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 28 Apr 2003 13:25:00 +0000 (13:25 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 28 Apr 2003 13:25:00 +0000 (13:25 +0000)
Many files:
  Pass dom_id and other flags to domains in start_info structure. Allow changing of IO privilege level via new hypercall.

xen/arch/i386/entry.S
xen/arch/i386/process.c
xen/common/domain.c
xen/include/hypervisor-ifs/hypervisor-if.h
xen/include/xeno/sched.h
xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/ioport.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/kernel/process.c
xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h

index afb4a5c54c740b19d93f25ece314511c3eed1288..f14f594ee52ef3e8e4fd3e5cb7b6ab4cf2aab18d 100644 (file)
@@ -647,6 +647,7 @@ ENTRY(hypervisor_call_table)
         .long SYMBOL_NAME(do_dom_mem_op)
         .long SYMBOL_NAME(do_multicall)
         .long SYMBOL_NAME(do_kbd_op)
+        .long SYMBOL_NAME(do_iopl)
         .rept NR_syscalls-((.-hypervisor_call_table)/4)
         .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 85f438f4fa8b0b3cfe3e9a69719890026645d81b..2cac1a9d4e373d1c5a13f98525b4cd69e10aa910 100644 (file)
@@ -31,6 +31,9 @@
 #include <xeno/irq.h>
 #include <xeno/event.h>
 
+#define GET_SYSCALL_REGS(_p) \
+    (((struct pt_regs *)(THREAD_SIZE + (unsigned long)(_p))) - 1)
+
 asmlinkage void ret_from_newdomain(void) __asm__("ret_from_newdomain");
 
 int hlt_counter;
@@ -247,9 +250,7 @@ void new_thread(struct task_struct *p,
                 unsigned long start_stack,
                 unsigned long start_info)
 {
-    struct pt_regs * regs;
-
-    regs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
+    struct pt_regs *regs = GET_SYSCALL_REGS(p);
     memset(regs, 0, sizeof(*regs));
 
     /*
@@ -345,3 +346,12 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
     }
 
 }
+
+
+long do_iopl(unsigned int new_iopl)
+{
+    struct pt_regs *regs = GET_SYSCALL_REGS(current);
+    if ( !IS_PRIV(current) ) return -EPERM;
+    regs->eflags = (regs->eflags & 0xffffcfff) | ((new_iopl&3) << 12);
+    return 0;
+}
index 1f3a2dd406f6dc48d9e97f222ef067062b01efb5..349acc5b578e98d2c845ce5f030c0816f63a705c 100644 (file)
@@ -357,6 +357,9 @@ int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
     virt_startinfo_addr->mod_start = meminfo->virt_mod_addr;
     virt_startinfo_addr->mod_len   = meminfo->virt_mod_len;
 
+    virt_startinfo_addr->dom_id = p->domain;
+    virt_startinfo_addr->flags  = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
+
     if( virt_startinfo_addr->mod_len )
        printk("Initrd module present %08lx (%08lx)\n",
                virt_startinfo_addr->mod_start, 
@@ -618,6 +621,9 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
     virt_startinfo_address->pt_base = virt_load_address + 
         ((p->tot_pages - 1) << PAGE_SHIFT); 
 
+    virt_startinfo_address->dom_id = p->domain;
+    virt_startinfo_address->flags  = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
+
     if ( initrd_len )
     {
        virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len;
index 7e5499aad7748e90ff420b38423b109d38842b3a..6b74f92b6675b151d2d6ae2a0654e0ad98c23a03 100644 (file)
@@ -48,6 +48,7 @@
 #define __HYPERVISOR_dom_mem_op                  17
 #define __HYPERVISOR_multicall           18
 #define __HYPERVISOR_kbd_op               19
+#define __HYPERVISOR_iopl                 20
 
 /* And the trap vector is... */
 #define TRAP_INSTR "int $0x82"
@@ -242,9 +243,14 @@ typedef struct start_info_st {
     unsigned long net_rings[MAX_DOMAIN_VIFS];
     /* Machine address of block-device ring. Will be page aligned. */
     unsigned long blk_ring;
+    unsigned int  dom_id;
+    unsigned long flags; 
     unsigned char cmd_line[1];   /* variable-length */
 } start_info_t;
 
+/* These flags are passed in the 'flags' field of start_info_t. */
+#define SIF_PRIVILEGED 1          /* Is thie domain privileged? */
+
 /* For use in guest OSes. */
 extern shared_info_t *HYPERVISOR_shared_info;
 
index ed3c0a71a118e8e94524b81bf3ab2b64837d4dd6..69da5c114589da7e350509f99a1acd16f559f71f 100644 (file)
@@ -60,8 +60,11 @@ extern struct mm_struct init_mm;
 #include <xeno/block.h>
 #include <xeno/segment.h>
 
-struct task_struct {
+/* SMH: replace below when have explicit 'priv' flag or bitmask */
+#define IS_PRIV(_p) ((_p)->domain == 0) 
 
+struct task_struct 
+{
     /*
      * DO NOT CHANGE THE ORDER OF THE FOLLOWING.
      * Their offsets are hardcoded in entry.S
@@ -72,10 +75,6 @@ struct task_struct {
     int hyp_events;              /* 08: pending intra-Xen events */
     unsigned int domain;         /* 12: domain id */
 
-    // SMH: replace below when have explicit 'priv' flag or bitmask
-#define IS_PRIV(_p) ((_p)->domain == 0) 
-
-
     /* An unsafe pointer into a shared data area. */
     shared_info_t *shared_info;  /* 16: shared data area */
 
index 798c5c5c1fc4509fb774271aeec9fd75e065b9a1..c43daee3fd50d8327d4a8899fe8e4cddd89ae874 100644 (file)
@@ -7,13 +7,30 @@
 
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
-    /* No IO permission! */
-               return -EPERM;
+    /* No IO permission! Selective IO perms aren't virtualised yet. */
+    return -EPERM;
 }
 
 
 asmlinkage int sys_iopl(unsigned long unused)
 {
-    /* The hypervisor won't allow it! */
-                       return -EPERM;
+    struct pt_regs *regs = (struct pt_regs *)&unused;
+    unsigned int level = regs->ebx;
+    unsigned int old = (regs->eflags >> 12) & 3;
+
+    if ( !(start_info.flags & SIF_PRIVILEGED) )
+        return -EPERM;
+
+    if ( level > 3 )
+        return -EINVAL;
+    if ( (level > old) && !capable(CAP_SYS_RAWIO) )
+        return -EPERM;
+    
+    /* Change the one on our stack for sanity's sake. */
+    regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
+
+    /* Force the change at ring 0. */
+    HYPERVISOR_iopl(level);
+
+    return 0;
 }
index d4db66747402aa93f37a90c298d3834848218e17..a7c0755d38d107f61d95b6a0467eb2a25006788a 100644 (file)
@@ -363,7 +363,12 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
     }
 
     if ( next->esp0 != 0 )
+    {
         queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0);
+        /* Next call will silently fail if we are a non-privileged guest OS. */
+        queue_multicall1(__HYPERVISOR_iopl, 
+                         ((((struct pt_regs *)next->esp0)-1)->eflags>>12)&3);
+    }
 
     /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */
     execute_multicall_list();
index 935ea3a6ef9b22e15909319719315bca880fadb7..a7a85110c51ffa228b8acb8684a1d94f9254635e 100644 (file)
@@ -353,7 +353,6 @@ static inline int HYPERVISOR_multicall(void *call_list, int nr_calls)
     return ret;
 }
 
-
 static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val)
 {
     int ret;
@@ -365,4 +364,15 @@ static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val)
     return ret;
 }
 
+static inline long HYPERVISOR_iopl(unsigned int new_iopl)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_iopl),
+        "b" (new_iopl) );
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */